/*******************************************************************
 * author   :  Charlies-ls
 * Date     :  2021-09-26
 * Copyright (c) 2021. artestplay@outlook.com. All Rights Reserved.
 *******************************************************************/
#include "com.h"
#include "ax_thread.h"
#include <memory.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <pthread.h>

#ifdef S700
struct timespec
{
    time_t tv_sec;            /* Seconds.  */
    long int tv_nsec;           /* Nanoseconds.  */
};
#endif

ax_mutex_t* ax_mutex_create()
{
    ax_mutex_t *m = (ax_mutex_t*)malloc(sizeof(ax_mutex_t));
    int ret = pthread_mutex_init(m, 0);
    if(ret!=0)
    {
        free(m);
        return NULL;
    }
    return m;
}

void ax_mutex_destroy(ax_mutex_t* m)
{
    if(m)
    {
        pthread_mutex_destroy(m);
        free(m);
    }
}

bool ax_mutex_lock(ax_mutex_t* m)
{
    if(m)
    {
        int ret = pthread_mutex_lock(m);
        return 0 == ret;
    }
    return false;
}

bool ax_mutex_unlock(ax_mutex_t*m)
{
    if(m)
    {
        return 0 == pthread_mutex_unlock(m);
    }
    return false;
}

bool ax_mutex_try_lock(ax_mutex_t*m)
{
    if(m)
    {
        return 0 == pthread_mutex_trylock(m);
    }
    return false;
}

ax_thread_t ax_thread_start(ax_thread_fun fun,void*param)
{
    ax_thread_t t;
    int ret = pthread_create(&t, NULL, fun, param);
    if(ret!=0)
    {
        return  (ax_thread_t)*(ax_thread_t*)(-1);
    }
    return t;
}

bool ax_thread_wait(ax_thread_t* thread)
{
    if(thread)
    {
        return 0 == pthread_join( (pthread_t)*thread, NULL);
    }
    return false;
}

bool ax_thread_cancel(ax_thread_t* t)
{
#ifndef ANDROID
    if(t)
    {
        return 0 == pthread_cancel(*(pthread_t*)t);
    }
#endif
    return false;
}

bool ax_thread_is_cancel(ax_thread_t*t)
{
    if(t)
    {
        // pthread_testcancel();
    }
    return false;
}

ax_cond_t* ax_cond_create()
{
    ax_cond_t *c = (ax_cond_t*)malloc(sizeof(ax_cond_t));
    pthread_cond_init(c,NULL);
    return c;
}

void ax_cond_destroy(ax_cond_t*m)
{
    if(m)
    {
        pthread_cond_destroy(m);
        free(m);
    }
}

bool ax_cond_wait(ax_cond_t*cond,ax_mutex_t*mutex)
{
    return 0 == pthread_cond_wait(cond,mutex);
}

bool ax_cond_wait_timeout(ax_cond_t*cond,ax_mutex_t*mutex,double seconds)
{
    return ax_cond_wait_timeout_ms(cond,mutex,seconds*1000);
}

bool ax_cond_wait_timeout_ms(ax_cond_t*cond,ax_mutex_t*mutex,double ms)
{
    int time_ms = (int)ms;
    struct timeval tv;
    struct timespec ts;

    gettimeofday(&tv, NULL);
    ts.tv_sec = time(NULL) + time_ms / 1000;
    ts.tv_nsec = tv.tv_usec * 1000 + 1000 * 1000 * (time_ms % 1000);
    ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
    ts.tv_nsec %= (1000 * 1000 * 1000);

    return 0 == pthread_cond_timedwait(cond,mutex,&ts);

}

bool ax_cond_signal(ax_cond_t* cond)
{
    return 0 == pthread_cond_signal(cond);
}
